package com.heima.comment.service.impl;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import com.heima.comment.service.CommentHotService;
import com.heima.comment.service.CommentService;
import com.heima.common.exception.CustException;
import com.heima.feigns.UserFeign;
import com.heima.model.comment.dtos.CommentDto;
import com.heima.model.comment.dtos.CommentLikeDto;
import com.heima.model.comment.dtos.CommentSaveDto;
import com.heima.model.comment.pojos.ApComment;
import com.heima.model.comment.pojos.ApCommentLike;
import com.heima.model.comment.vos.ApCommentVo;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.threadlocal.AppThreadLocalUtils;
import com.heima.model.user.pojos.ApUser;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.checkerframework.checker.units.qual.A;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

@Slf4j
@Service
public class CommentServiceImpl implements CommentService {
    public static final ResponseResult Re = null;
    @Autowired
    MongoTemplate mongoTemplate;
    @Autowired
    UserFeign userFeign;
    @Override
    public ResponseResult saveComment(CommentSaveDto dto) {
        //1.检查参数
        //2.登录校验
        ApUser user = AppThreadLocalUtils.getUser();
        if (user==null) {
            CustException.cust(AppHttpCodeEnum.NEED_LOGIN);
        }
        //3.调用feign接口查询用户信息
        ResponseResult<ApUser> result = userFeign.findUserById(user.getId());
        if (result.getCode().intValue()!=0||result.getData()==null) {
            CustException.cust(AppHttpCodeEnum.SERVER_ERROR,"远程调用userFeign.findUserById失败");
        }
        //4.保存评论信息到mongodb
        user = result.getData();
        ApComment apComment = new ApComment();
        apComment.setAuthorId(user.getId());
        apComment.setAuthorName(user.getName());
        apComment.setArticleId(dto.getArticleId());
        apComment.setType((short)0);
        apComment.setContent(dto.getContent());
        apComment.setImage(user.getImage());
        apComment.setLikes(0);
        apComment.setReply(0);
        apComment.setFlag((short)0);
        apComment.setCreatedTime(new Date());
        apComment.setUpdatedTime(new Date());
        mongoTemplate.save(apComment);
        return ResponseResult.okResult();
    }
    @Autowired
    CommentHotService commentHotService;
    @Autowired
    RedissonClient redissonClient;
    @Override
    public ResponseResult like(CommentLikeDto dto) {
        ApUser user = AppThreadLocalUtils.getUser();
        if (user==null) {
            CustException.cust(AppHttpCodeEnum.NEED_LOGIN);
        }
        //查询出评论详情信息
        RLock lock = redissonClient.getLock("likes-lock");
        lock.lock();


        ApComment apComment;
        try {
            apComment = mongoTemplate.findById(dto.getCommentId(), ApComment.class);
            if (apComment==null) {
                CustException.cust(AppHttpCodeEnum.DATA_NOT_EXIST);
            }
            //查询数据库是否有对当前评论已经点过赞，有则报异常，无则创建
            Query query = Query.query(Criteria.where("authorId").is(user.getId()).and("commentId").is(dto.getCommentId()));
            ApCommentLike commentLike = mongoTemplate.findOne(query, ApCommentLike.class);
            if (dto.getOperation().intValue() == 0) {
                if (commentLike != null) {
                    CustException.cust(AppHttpCodeEnum.DATA_EXIST, "已经点过赞，请勿重复操作");
                }
                commentLike = new ApCommentLike();
                commentLike.setAuthorId(user.getId());
                commentLike.setCommentId(dto.getCommentId());
                commentLike.setOperation((short) 0);
                mongoTemplate.save(commentLike);
                //评论点赞数量加一
                apComment.setLikes(apComment.getLikes()+1);
                mongoTemplate.save(apComment);
                //计算热点评论评论
                if (apComment.getLikes() >= 10 && apComment.getFlag().shortValue() == 0) {
                    commentHotService.hotCommentExecutor(apComment);
                }
            } else {
                //取消点赞
                mongoTemplate.remove(query,ApCommentLike.class);
                //评论点赞数量减一
                apComment.setLikes(apComment.getLikes()<1?0:apComment.getLikes()-1);
                mongoTemplate.save(apComment);
            }
        } finally {
            lock.unlock();
        }
        //4 数据返回
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("likes",apComment.getLikes());
        return ResponseResult.okResult(resultMap);
    }

    @Override
    public ResponseResult findByArticleId(CommentDto dto) {
        //1.检查参数
        if (dto.getSize()==null||dto.getSize()<=0) {
            dto.setSize(10);
        }
        if (dto.getMinDate()==null) {
            dto.setMinDate(new Date());
        }
        List<ApComment> commentList;
        if (dto.getIndex().intValue() == 1) {
            //查询热点评论
            commentList = mongoTemplate.find(Query.query(Criteria.where("articleId").is(dto.getArticleId())
                    .and("flag").is(1))
                    .with(Sort.by(Sort.Direction.DESC, "likes")), ApComment.class);
            //总个数减去热点评论个数
            int size = dto.getSize() - commentList.size();
            //查询除去热点评论之外的普通评论
            List<ApComment> normalComments = mongoTemplate.find(Query.query(Criteria.where("articleId").is(dto.getArticleId())
                    .and("createdTime").lt(dto.getMinDate())
                    .and("flag").is(0))
                    .with(Sort.by(Sort.Direction.DESC, "createdTime"))
                    .limit(size), ApComment.class);
            //合并评论
            commentList.addAll(normalComments);
        } else {
            //2.用户是否登录，未登录查询评论列表
            //滚动分页查询，查询创建时间小于最小时间，即十条评论中最后一条的创建时间为最小时间
             commentList = mongoTemplate.find(Query.query(Criteria.where("articleId").is(dto.getArticleId())
                    .and("createdTime").lt(dto.getMinDate())
                    .and("flag").is(0))
                    .limit(dto.getSize())
                    .with(Sort.by(Sort.Direction.DESC, "createdTime")), ApComment.class);
        }



        ApUser user = AppThreadLocalUtils.getUser();
        if (user==null) {
            return ResponseResult.okResult(commentList);
        }
        //3.用户登录查询点赞列表
        ArrayList<ApCommentVo> commentVoArrayList = new ArrayList<>();
        //本文章内的所有评论的Id
        List<Object> idList = commentList.stream().map(ApComment::getId).collect(Collectors.toList());
        //用户点过赞的评论
        List<ApCommentLike> apCommentLikes = mongoTemplate.find(Query.query(Criteria.where("commentId").in(idList).and("authorId").is(user.getId())), ApCommentLike.class);
        List<String> idLikeList = apCommentLikes.stream().map(ApCommentLike::getCommentId).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(commentList)&&CollectionUtils.isNotEmpty(apCommentLikes)) {
            //遍历评论集合
            commentList.forEach(apComment -> {
                //将评论拷贝到评论vo
                ApCommentVo apCommentVo = new ApCommentVo();
                BeanUtils.copyProperties(apComment,apCommentVo);
                //遍历用户点过赞的集合比较  点过赞的评论的id 和 内容的id 如果一致那么设置对应的vo的operation为点赞状态
                    if (idLikeList.contains(apComment.getId())) {
                        apCommentVo.setOperation((short) 0);
                    }
                commentVoArrayList.add(apCommentVo);
            });
            return ResponseResult.okResult(commentVoArrayList);
        }
        return ResponseResult.okResult(commentList);
    }
}
